#pragma once
#include<unistd.h>
#include"Task.hpp"
#include<signal.h>
#include<sys/wait.h>
#include<cstdlib>
#include<cstring>
#include"Threadpool.hpp"
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<sys/fcntl.h>
#include<netinet/in.h>
using namespace std;
#define BACK_LOG 4
#define DFL_PORT 8081
class TcpServer
{
  private:
    int _port;
    int listen_sock;
    ThreadPool<Task>* tp;
  public:
    TcpServer(int port=DFL_PORT)
      :_port(port)
      ,listen_sock(-1)
      ,tp(nullptr)
    {}
    void InitServer()
    {
      listen_sock=socket(AF_INET,SOCK_STREAM,0);
      if(listen_sock<0)
      {
        cerr<<"socket error"<<endl;
        exit(2);
      }
     struct sockaddr_in local;
     memset(&local,0,sizeof(local));
     local.sin_family=AF_INET;
     local.sin_port=htons(_port);
     cout<<_port<<endl;
     local.sin_addr.s_addr=INADDR_ANY;
     //弱化IP强调端口，凡是端口号是服务器的我都处理
     //inet_addr("192.0.0.1");将点分十进制字符串风格的ip转化成四字节的整数风格的ip地址
     
      if(bind(listen_sock,(struct sockaddr*)& local,sizeof(local))<0)
        {
            cerr<<"bind error"<<endl;
            exit(3);
        }
        //监听
        if(listen(listen_sock,BACK_LOG)<0)
        {
          cerr<<"listen error"<<endl;
          exit(4);
        }
        tp=new ThreadPool<Task>();
    }
    class Pragma
    {
      public:
        int _sock;
        string _ip;
        int _port;
        Pragma(int sock,string ip,int port)
          :_sock(sock)
          ,_ip(ip)
          ,_port(port)
        {}    
    };
    static void* HandlerRequest(void* arg)
    {
      Pragma* p=(Pragma*)arg;
      pthread_detach(pthread_self());
      close(p->_sock);
      delete p;
      return nullptr;
    }
    void Loop()
    {
      tp->InitThreadPool();
      struct sockaddr_in peer;
      for(;;)
      {
        socklen_t len=sizeof(peer);
        int sock=accept(listen_sock,(struct sockaddr*)& peer,&len);
        if(sock<0)
        {
          cout<<"accept error continue"<<endl;
          continue;
        }
        string ip=inet_ntoa(peer.sin_addr);
        int port=ntohs(peer.sin_port);
        Task t(sock,ip,port);
        tp->Push(t);
      }
    }
    //echo
    ~TcpServer()
    {
      if(listen_sock>=0)
      {
        close(listen_sock);
      }
    }
};
